if lib and not lib.exists then


function lib:exists(file)
	local ok, err, code = os.rename(file, file)
	
	if not ok then
		if code == 13 then
			-- Permission denied, but it exists
			return true
		end
	end
	return ok
end


function lib:isDir(path)
	return self:exists(path  .. "\\")
end


function lib:isFile(path)
	return self:exists(path) and not self:isDir(path)
end


function lib:basename(path)
	local str = path:match("([^/\\]+)$")
	
	if str == nil then return "" end
	
	return str
end


function lib:dirname(path)
	local str = path:match("(.*[/\\])")
	
	if str == nil then return "" end
	
	return str
end


function lib:remove(path)
	local dirname = self:dirname(path)
	local filename = self:basename(path)
	
	if filename:len() > 0 then
		dirname = dirname .. "trash\\" .. self:FormatSysdate() .. "."
		
		if os.rename(path, dirname .. filename) then
			return true
		end
	end
	
	return os.remove(path)
end


function lib:AddLine(file, text)
	if not file then return end
	local hf, i
	for i = 1, 10 do
		hf = io.open(file, "a")
		if hf then break end
		sleep(100)
	end
	if not hf then return end
	hf:write(tostring(text) .. "\n")
	hf:close()
	return true
end


function lib:LoadFile(file)
	local hf = io.open(file, "r")
	if hf then
		local list = {}
		for l in hf:lines() do
			table.insert(list, l)
		end
		hf:close()
		return list
	end
end


function lib:SaveFile(file, data, delim)
	if type(file) == "string" then
		local hf = io.open(file .. ".tmp", "w")
		if hf then
			self:SaveFile(hf, data, delim)
			hf:close()
			self:remove(file)
			os.rename(file .. ".tmp", file)
			return true
		end
	elseif io.type(file) == "file" then
		if type(data) == "table" then
			for _, l in ipairs(data) do
				if type(l) == "table" then
					delim = delim or "\t"
					local s
					for _, c in ipairs(l) do
						if s then
							s = s .. delim .. tostring(c)
						else
							s = tostring(c)
						end
					end
					if s then
						file:write(s .. "\n")
					else
						file:write("\n")
					end
				else
					file:write(tostring(l) .. "\n")
				end
			end
		else
			file:write(tostring(data) .. "\n")
		end
	end
end


function lib:LoadLabels(sec_code, ttl)
	ttl = ttl or self.global.file_ttl
	local file
	local instrument
	
	if sec_code then
		sec_code = string.upper(sec_code)
		if string.match(sec_code, "[\\/]") then
			file = sec_code
		else
			instrument = self:GetInstrument(sec_code)
			file = lib.path.labels .. "labels." .. sec_code
			if not self:exists(file) and string.match(sec_code, "^%a%a%a%d$") then	-- Futures
				for i = 1, 2 do
					file = lib.path.labels .. "labels." .. string.sub(sec_code, 1, -3) .. tostring(i) .. "!"
					if self:exists(file) then break end
				end
			end
		end
	else
		file = self:LoadFile(lib.path.labels .. "labels.last")
		if file then
			instrument = self:GetInstrument(file[1])
			if instrument then
				file = lib.path.labels .. "labels." .. file[1]
			else
				file = nil
			end
		end
	end
	
	if file then
		local hf = io.open(file, "r")
		if hf then
			local labels
			local date = hf:read()
			local seconds = int(hf:read())
			
			if date == lib:FormatDate() and lib:tickseconds() - seconds <= ttl then
				local label, str, pr, sh
				labels = {seconds_ = seconds}
				str = hf:read()
				while str do
					label, str = string.match(str, "^%s*([%a_]+)%s*=%s*(%S+)")
					if label and str then
						pr, sh = string.match(str, "^([%d%.]+)%-(%d+)$")
						if pr and sh and instrument then
							labels[label] = tonumber(pr) - tonumber(sh) * instrument.min_price_step
						else
							pr, sh = string.match(str, "^([%d%.]+)%+(%d+)$")
							if pr and sh and instrument then
								labels[label] = tonumber(pr) + tonumber(sh) * instrument.min_price_step
							elseif string.match(str, "^[%d%.]+$") then
								labels[label] = tonumber(str)
							else
								labels[label] = str
							end
						end
					end
					str = hf:read()
				end
			end
			hf:close()
			
			if not labels then
				self:remove(file)
			end
			
			return labels, instrument
		end
	end
end


function lib:SaveLabels(sec_code, labels)
	labels = labels or {}
	if lib.path.labels and sec_code and type(labels) == "table" then
		local file
		if string.match(sec_code, "[\\/]") then
			file = sec_code
			sec_code = nil
		else
			file = lib.path.labels .. "labels." .. sec_code
		end
		local hf = io.open(file .. ".tmp", "w")
		if hf then
			hf:write(lib:FormatDate() .. "\n")
			hf:write(lib:tickseconds() .. "\n")
			for label, str in pairs(labels) do
				hf:write(label .. "=" .. str .. "\n")
			end
			hf:close()
			self:remove(file)
			os.rename(file .. ".tmp", file)
			if sec_code then
				self:SaveFile(lib.path.labels .. "labels.last", sec_code)
			end
		end
	end
end


function lib:LoadIni(file, section, def)
	def = def or {}
	if file then
		local hf = io.open(file, "r")
		if hf then
			local ini = hf:read("*a")
			local l = string.len(ini)
			hf:close()
			if section then
				ini = string.gsub(ini, "^.*\n%[" .. section .. "%]", "")
				ini = string.gsub(ini, "^%[" .. section .. "%]", "")
				if l == string.len(ini) then return def end
				ini = string.gsub(ini, "\n%[.*$", "")
			end
			def = lib:LoadString(ini, def)
		end
	end
	return def
end


end -- of file
